import Entity from "./Entity";
import DealRoom from "./DealRoom";
import LogicConfigTs from "../Utils/LogicConfigTs";

export default class Room extends Entity {

    /** 状态 0=准备开始 1=准备发牌(5秒) 2=游戏中 3=提交中(30秒) 4=准备下一局对战(6秒) 5=洗牌中(3秒) 6=准备下一轮对战(10秒) */
    static RoomState = {
        IDLE:0,
        PREPARE:1,
        IN_GAME:2,
        COMMITTING:3,
        BEFORE_NEXT_ROUND:4,
        SHUFFLING:5,    //shuffling
        INTERVAL:6, //CD BEFORE NEXT BATTLE
    }

    //用于展示的room id
    room_id = 0;
    //状态 0=未准备 1=游戏中 2=结算中 3=下一轮准备中 4=洗牌中 5=下一轮倒计时
    state = 0;
    //最大人数 2或6人
    p_max = 0;
    //游戏模式
    mode = 0;
    //剩余牌数
    c_num = 0;
    //明牌
    c_open = 0;
    //客户端牌堆
    c_open_objs = []
    //混子牌
    joker = 0;
    //客户端使用的joker对象
    joker_obj = null
    //当前出牌玩家
    c_id = 0;
    //本局第一个出牌玩家
    f_id = 0;
    //出牌倒计时
    timer_cd = 0;
    // //游戏时长计时器
    // timer = false;
    // //都准备后触发，参数是读秒数
    // prestart = 0;
    //倍数
    multi = 1
    //奖金，为了兼容deal模式，他是个数组
    prize = []
    //玩家比牌的序列
    comps = []

    en_class() {
        return 'Room';
    }

    /**
     * 玩家抓牌
     * @param id 玩家UID
     * @param from 1=明牌堆 2=剩余牌堆
     */
    _serv_grap(id, from) {

    }

    /**
     * 玩家提交牌组
     * @param id
     * @param cards
     */
    _serv_commit(id, cards) {

    }

    /**
     * 服务端生成的一轮结束后的得分报告
     * @param scores 得分报告 结构为[{id,score}]
     */
    _serv_report(scores) {

    }

    /**
     * 服务端生成的对局结束后的结算数据
     * @param trans 结算信息 结构为[{id,coin}]
     */
    _serv_finish(trans) {

    }

    clearDiscards(){
        cc.log("清空弃牌堆")
        this.c_open_objs = []
    }

    onCreate(){
        // this.info = cc.gg.gameDataUtil.roomInfo
        // cc.gg.gameDataUtil.roomInfo = null
    }

    onDestroy() {
        super.onDestroy()
        cc.gg.dataMgr.clearData()
    }

    closeRoom(){
        this.clearListeners()
    }

    openRoom(){
        let mode = this.mode
        let roomMode = cc.gg.enumConfig.RoomMode
        let modeBase = mode & 0x0f0
        if(modeBase === roomMode.BASE_VALUE_2){
            cc.director.loadScene('TwoPlayerGame',function () {
                this.startRoom()
                // if(this.state === 0 && this.timer_cd){
                //     // this.gameMgr.startWaitCountDown(this.timer_cd)
                //     cc.find("Canvas/UIManager").emit("ui_game_count_down_start",this.timer_cd)
                // }
            }.bind(this))
        }else if(modeBase === roomMode.BASE_VALUE_6){
            cc.director.loadScene('SixPlayerGame',function () {
                this.startRoom()
                // if(this.state === 0 && this.timer_cd){
                //     // this.gameMgr.startWaitCountDown(this.timer_cd)
                //     cc.find("Canvas/UIManager").emit("ui_game_count_down_start",this.timer_cd)
                // }
            }.bind(this))
        }
    }

    startRoom(){
        if(this.state === 0 && this.timer_cd){
            // this.gameMgr.startWaitCountDown(this.timer_cd)
            cc.find("Canvas/UIManager").emit("ui_game_count_down_start",this.timer_cd)
        }
    }

    initRoom(gameMgr){
        this.gameMgr = gameMgr
        //modify event
        this.c_open_objs = cc.gg.dataMgr.convertToClientPokerObj(this.c_open)
        this.joker_obj = cc.gg.dataMgr.convToClientPokerObj(this.joker)

        this.onModifyEvent('state', (state) => this.onStateChange(state));
        this.onModifyEvent('c_num', (c_num) => this.onCardNumChange(c_num));
        this.onModifyEvent('c_open', (c_open) => this.onOpenCardChange(c_open));
        this.onModifyEvent('joker', (joker) => this.onJokerChange(joker));
        this.onModifyEvent('c_user', (id) => this.onCUserChange(id));
        // this.onModifyEvent('timer', (timer) => this.onTimerChange(timer));
        this.onModifyEvent('f_id', (f_id) => this.onfUIDChange(f_id));
        this.onModifyEvent('c_id', (f_id) => this.onCUIDChange(f_id));
        this.onModifyEvent('timer_cd',(turn_cd) => this.onTurnCDChanged(turn_cd))
        this.onModifyEvent('prize',(data) => this.onPrize(data))
        this.onModifyEvent('round',(data) => this.onRound(data))
        //trigger event
        this.onTriggerEvent('grab', (id, from) => this.onUserGrab(id, from));
        this.onTriggerEvent('discard', (id, card) => this.onUserDiscard(id, card));
        this.onTriggerEvent('finish', (data) => this.onRoomFinish(data));
        this.onTriggerEvent('commit', (id, cards, score) => this.onUserCommit(id, cards, score));
        this.onTriggerEvent('report', (scores) => this.onReport(scores));
        this.onTriggerEvent('result', (data) => this.onResult(data));
    }

    onRound(data){
        cc.log("on round:",data)
        data = parseInt(data)
        this.round = data
        if(this.round === 1){
            cc.find("Canvas/UIManager").emit("ui_clear_deal_board")
        }
    }

    onPrize(data){
        cc.log("收到prize：",data)
        this.prize = data
        let championPrize = this.prize ? this.prize[0].coin : 0
        championPrize = championPrize ? championPrize : 0
        cc.log("championPrize:",championPrize)
        cc.find("Canvas").emit("msgwatcher_add",function () {
            if(this._addedTopBar){
                let topBarNode = this.getTopBar()
                let topBarScript = topBarNode.getComponent("TopInfoBar")
                topBarScript.updatePrizeThumb(championPrize)
                return true
            }
            return false
        }.bind(cc.gg.tpgMgr.uiMgr))
    }

    onResult(data){
        cc.gg.gameDataUtil.resultJustNow = true
        cc.gg.gameDataUtil.gameStarted = false

        let baseScore = 0
        if(this instanceof DealRoom){
            baseScore = this.baseScore
        }
        cc.gg.dataMgr.clearAllUserTotalScore(baseScore)
    }

    onRoomFinish(data){
        cc.gg.gameDataUtil.receiveFinish = true
        cc.gg.gameDataUtil.resultJustNow = false
        let id = data[0]
        let cards = data[1]
        let finishCard = data[2]
        // let groupTime = data[3]
        let groupTime = this.timer_cd

        finishCard = cc.gg.dataMgr.convToClientPokerValue(finishCard)

        let user = cc.gg.dataMgr.getUser(id)
        let resultObj = {
            id:id,
            name:user.name,
            cards:this.convToClientPokerValueArray(cards)
        }
        cc.find("Canvas").emit("flow_start_group_passive",id,resultObj,finishCard,groupTime)
    }

    onTurnCDChanged(turn_cd){
        cc.log("onTurnCDChanged=========",turn_cd,"  ",this.state)
        this.timer_cd = turn_cd

        if(this.state === Room.RoomState.IDLE){
            // this.gameMgr.startWaitCountDown(this.timer_cd)
            cc.find("Canvas/UIManager").emit("ui_game_count_down_start",this.timer_cd)
        }else if(this.state === Room.RoomState.PREPARE){
            // this.gameMgr.startWaitCountDown(this.timer_cd)
            cc.find("Canvas/UIManager").emit("ui_game_count_down_start",this.timer_cd)
        }else if(this.state === Room.RoomState.IN_GAME){

        }else if(this.state === Room.RoomState.COMMITTING){

        }else if(this.state === Room.RoomState.BEFORE_NEXT_ROUND){
            // this.gameMgr.startWaitCountDown(this.timer_cd)
            cc.find("Canvas/UIManager").emit("ui_game_count_down_start",this.timer_cd)
        }else if(this.state === Room.RoomState.SHUFFLING){

        }else if(this.state === Room.RoomState.INTERVAL){
            // this.gameMgr.startWaitCountDown(this.timer_cd)
            cc.find("Canvas/UIManager").emit("ui_game_count_down_start",this.timer_cd)
        }else {

        }

        //结算板
        if(this.state === Room.RoomState.BEFORE_NEXT_ROUND || Room.RoomState.INTERVAL){
            cc.find("Canvas").emit("dealinfo_start_count_down",this.timer_cd)
        }
    }

    onUserGrab(data){

        cc.log("Room收到grab消息！",data)
        let id = data[0]
        let from = parseInt(data[1])
        cc.logws("Room Receive:"+id+" grab a card from ",from)

        let topPokerObj = null
        if(from === cc.gg.enumConfig.GrabFrom.DISCARDS){
            this.c_open.pop()
            cc.log(" c_open变更为：",this.c_open)
            topPokerObj = this.c_open_objs.pop()
            cc.log(" c_open_objs减少为：",this.c_open_objs)
        }

        if(id !== cc.gg.dataMgr.getPlayerGameId())
            cc.find("Canvas").emit("game_oponnent_grap",id,from)
        else if(from === cc.gg.enumConfig.GrabFrom.DISCARDS){
            //由于客户端poker有id的存在，弃牌堆只能从弃牌堆里拿旧牌，而不能生成一张新的牌，否则会导致poker的id对应不上
            cc.find("Canvas").emit("game_self_grap",id,from,topPokerObj)
        }
    }

    onUserDiscard(data){
        let id = data[0]
        let card = cc.gg.dataMgr.convToClientPokerValue(data[1])

        let newCard = cc.gg.dataMgr.generateNewPoker(card)

        this.c_open_objs.push(newCard)

        if(id !== cc.gg.dataMgr.getPlayerGameId())
            cc.find("Canvas").emit("flow_opponent_discard",id,{id:cc.gg.dataMgr.generateNewPokerId(), poker:card})
        else {
            let user = cc.gg.dataMgr.getUser(id)
            console.assert(user)
            user.dropCard(card)
            cc.find("Canvas").emit("player_discard_passive",card)
        }
    }

    onUserCommit(data){
        let id = data[0]
        cc.log("用户",data,"提交手牌！",cc.gg.dataMgr.getPlayerGameId())
        let cards = this.convToClientPokerValueArray(data[1])


        if(id === cc.gg.dataMgr.getPlayerUser().id){
            cc.find("Canvas/UIManager").emit("ui_show_view_node",true)
            cc.find("Canvas/UIManager").emit("ui_show_btn_declare",false)
            cc.find("Canvas/UIManager").emit("ui_show_score",true)
            cc.gg.tpgMgr.clearCommittingUser(cc.gg.dataMgr.getPlayerUser())
        }else {
            let otherUser = cc.gg.dataMgr.getUser(id)
            cc.gg.tpgMgr.clearCommittingUser(otherUser)
        }
        // cc.find("Canvas/UIManager").emit("ui_update_deal_info_board",{id:id,cards:cards})

        cc.find("Canvas/UIManager").emit("ui_update_dealinfo_cards",id,cards)

        let isAllCommit = true
        for(let i in cc.gg.dataMgr.users){
            let user = cc.gg.dataMgr.users[i]
            if(user.b_state !== 3){
                isAllCommit = false
                break
            }
        }
        if(isAllCommit){
            cc.gg.tpgMgr.clearAllCommittingUsers()
            cc.find("Canvas/UIManager").emit("ui_show_score",false)
        }

    }

    onReport(scores){
        cc.logws("Room.onReport:",scores)
        cc.gg.gameDataUtil.resultJustNow = false
        scores = scores[0]

        for(let i=0;i<scores.length;i++){
            let obj1 = scores[i]
            let id = obj1.id
            let score = obj1.score

            let userObj = cc.gg.dataMgr.getUser(id)
            if(userObj) {
                userObj.score += score
                cc.find("Canvas").emit("ui_update_head_score",id,userObj.score)
            }

            cc.find("Canvas/UIManager").emit("ui_update_dealinfo_scores",obj1.id,score,userObj.score,true)
            // cc.find("Canvas/UIManager").emit("ui_update_deal_info_board",{id:obj1.id,score:obj1.score,totalScore:userObj.score})
        }
        cc.find("Canvas/UIManager").emit("ui_show_score",false)
        // cc.gg.emitEvent("dealinfo_start_count_down",this.timer_cd)
        this.updateWinner(scores)
    }

    /**
     * can be used to points and deal
     * @param scores
     */
    updateWinner(scores){
        cc.log("开始更新赢家：",scores)

        let biggestUser = null
        for(let i in scores){
            let tmpUser = scores[i]
            let id = tmpUser.id
            let score = tmpUser.score

            // let userObj = cc.gg.dataMgr.getUser(id)
            // if(!userObj) continue
            //
            // if(!biggestUser){
            //     biggestUser = userObj
            //     continue
            // }
            if(!biggestUser){
                biggestUser = tmpUser
                continue
            }

            biggestUser = tmpUser.score > biggestUser.score ? tmpUser : biggestUser
        }
        cc.log("赢家是：",biggestUser.id)

        cc.find("Canvas/UIManager").emit("ui_update_dealinfo_winner",biggestUser.id)
    }

    onfUIDChange(f_id){
        this.f_id = f_id
        cc.log(`f_id:    首次出牌人改变: ${f_id}`)
        // cc.find("Canvas").emit("flow_player_turn",f_id,cc.gg.dataMgr.room.timer_cd,false)
        // cc.find("Canvas").emit("flow_player_turn",c_id,cc.gg.dataMgr.room.timer_cd,false)

        cc.gg.tpgMgr.updateDIndicator(this.comps)
    }

    onCUIDChange(c_id){
        this.c_id = c_id
        cc.logws(`c_id:    出牌人改变: ${c_id}`)
        cc.find("Canvas").emit("flow_player_turn",c_id,cc.gg.dataMgr.room.timer_cd,false)
    }

    onStateChange(state) {
        this.state = state
        let _state = '';
        switch (state) {
            case Room.RoomState.IDLE:
                this._justShuffled = false
                _state = '准备阶段';
                cc.find("Canvas").emit("reset_table")
                cc.find("Canvas").emit("close_windows")
                break;
            case Room.RoomState.PREPARE:
                cc.gg.gameDataUtil.resultJustNow = false
                cc.gg.dataMgr.noNeedToReconnect = false
                cc.find("Canvas").emit("reset_table")
                cc.find("Canvas").emit("close_dialogs")
                _state = '开局倒计时';
                break;
            case Room.RoomState.IN_GAME:
                cc.gg.gameDataUtil.resultJustNow = false
                _state = '游戏阶段';
                if(this._justShuffled){
                    this._justShuffled = false
                    break;
                }
                cc.find("Canvas").emit("reset_table")
                break;
            case Room.RoomState.COMMITTING:
                _state = '结算阶段';
                break;
            case Room.RoomState.BEFORE_NEXT_ROUND:
                _state = '下一局倒计时';
                cc.find("Canvas/UIManager").emit("ui_show_view_node",false)
                cc.find("Canvas").emit("reset_table")
                cc.find("Canvas").emit("close_windows")
                break;
            case Room.RoomState.SHUFFLING:
                _state = '洗牌中';
                this._justShuffled = true
                cc.find("Canvas").emit("flow_shuffle")
                break;
            case Room.RoomState.INTERVAL:
                cc.find("Canvas").emit("reset_table")
                cc.find("Canvas").emit("close_windows")
                _state = '下一轮倒计时';
                break;
        }
        cc.log(`房间状态改变: ${_state}`);
    }

    onCardNumChange(c_num) {
        cc.log(`剩余牌数改变: ${c_num}`);
    }

    onOpenCardChange(c_open) {
        this.c_open = c_open
        cc.log(`明牌堆改变: ${c_open}`);
    }

    onJokerChange(joker) {
        this.joker = joker
        cc.log(`混子牌改变: ${joker}`);
    }

    onCUserChange(id) {
        this.c_id = id
        cc.log(`出牌玩家切换: ${id}`);
    }

    // onTimerChange(timer) {
    //     cc.logws('计时器更新:', timer);
    //     if(this.state === 3 || this.state === 5){
    //         cc.find("Canvas").emit("dealinfo_start_count_down",this.timer_cd)
    //     }
    // }

     getDicards(count){
        let topDiscards = []
        let startIdx = this.c_open_objs.length - count
        for(let i=startIdx;i<this.c_open_objs.length;i++){
            topDiscards.push(this.c_open_objs[i])
        }
        return topDiscards
    }


    convToClientPokerValueArray (serCardValueArray) {
        let serverArr = []
        for(let i=0;i<serCardValueArray.length;i++){
            let tmpArr = []
            for(let j=0;j<serCardValueArray[i].length;j++){
                tmpArr.push(this.convToClientPokerValue(serCardValueArray[i][j]))
            }
            serverArr.push(tmpArr)
        }
        return serverArr
    }


    convToClientPokerValue (cardValue) {
        let num = cc.gg.dataMgr.getPokerNum(cardValue)
        if(num === 14 && !cc.gg.dataMgr.isJoker(cardValue)){
            cardValue = cardValue >> 4
            cardValue = cardValue << 4
            cardValue += 1
        }
        return cardValue
    }

    getTotalScore(taruid){
        if(!this.scores)
             return 0

        for(let id in this.scores){
            let scoreArray = this.scores[id].scores
            if(parseInt(id) !== taruid) continue

            let totalScore = 0
            for(let i=0;i<scoreArray.length;i++){
                let num = scoreArray[i]
                totalScore += num
            }

            return totalScore
        }

        return 0
    }

    // getAvatarOriginScore(){
    //     return this.score
    // }

    //得到当前退出的话，算不算强制退出（会不会算作失败）
    isForceQuit(){
        return this.state === Room.RoomState.PREPARE ||
            this.state === Room.RoomState.IN_GAME ||
            this.state === Room.RoomState.COMMITTING ||
            this.state === Room.RoomState.SHUFFLING ||
            this.state === Room.RoomState.BEFORE_NEXT_ROUND
    }
}